package com.clp.util.hutool.core.bean.copier;

import com.clp.util.hutool.core.lang.Editor;
import com.clp.util.hutool.core.map.MapUtil;
import com.clp.util.hutool.core.util.ObjectUtil;

import java.util.Map;

public class CopyOptions {
    /**
     * 忽略的目标对象中属性列表，设置一个属性列表，不拷贝这些属性值
     */
    public String[] ignoreProperties;
    /**
     * 是否忽略字段注入错误
     */
    public boolean ignoreError;
    /**
     * 是否忽略字段大小写
     */
    public boolean ignoreCase;
    /**
     * 限制的类或接口，必须为目标对象的实现接口或父类，用于限制拷贝的属性，例如一个类我只想复制其父类的一些属性，就可以将editable设置为父类
     */
    protected Class<?> editable;
    protected boolean ignoreNullValue;
    /**
     * 字段属性编辑器，用于自定义属性转换规则，例如驼峰转下划线等
     */
    protected Editor<String> fieldNameEditor;
    /**
     * 拷贝属性的字段映射，用于不同的属性之前拷贝做对应表用
     */
    protected Map<String, String> fieldMapping;
    /**
     * 反向映射表，自动生成用于反向查找
     */
    protected Map<String, String> reversedFieldMapping;
    /**
     * 是否支持transient关键字修饰和@Transient注解，如果支持，被修饰的字段或方法对应的字段将被忽略。
     */
    private boolean transientSupport = true;

    public static CopyOptions create() {
        return new CopyOptions();
    }

    public CopyOptions() {}

    public CopyOptions setIgnoreNullValue(boolean ignoreNullValue) {
        this.ignoreNullValue = ignoreNullValue;
        return this;
    }

    public CopyOptions setFieldNameEditor(Editor<String> fieldNameEditor) {
        this.fieldNameEditor = fieldNameEditor;
        return this;
    }

    /**
     * 是否支持transient关键字修饰和@Transient注解，如果支持，被修饰的字段或方法对应的字段将被忽略。
     *
     * @return 是否支持
     * @since 5.4.2
     */
    public boolean isTransientSupport() {
        return this.transientSupport;
    }

    /**
     * 获得映射后的字段名<br>
     * 当非反向，则根据源字段名获取目标字段名，反之根据目标字段名获取源字段名。
     *
     * @param fieldName 字段名
     * @param reversed 是否反向映射
     * @return 映射后的字段名
     */
    protected String getMappedFieldName(String fieldName, boolean reversed) {
        Map<String, String> mapping = reversed ? getReversedMapping() : this.fieldMapping;
        if (MapUtil.isEmpty(mapping)) {
            return fieldName;
        }
        return ObjectUtil.defautIfNull(mapping.get(fieldName), fieldName);
    }

    /**
     * 转换字段名为编辑后的字段名
     * @param fieldName 字段名
     * @return 编辑后的字段名
     * @since 5.4.2
     */
    protected String editFieldName(String fieldName) {
        return (null != this.fieldNameEditor) ? this.fieldNameEditor.edit(fieldName) : fieldName;
    }

    private Map<String, String> getReversedMapping() {
        if (null == this.fieldMapping) {
            return null;
        }
        if (null == this.reversedFieldMapping) {
            reversedFieldMapping = MapUtil.reverse(this.fieldMapping);
        }
        return reversedFieldMapping;
    }

    public CopyOptions setIgnoreError(boolean ignoreError) {
        this.ignoreError = ignoreError;
        return this;
    }
}
